package main

import "fmt"

/*
panic 会立即终止当前函数的执行
会开始逐层向上执行每个函数的 defer 语句
如果没有 recover，程序会崩溃退出

recover必须在 defer 函数中调用才有效
可以捕获最近的 panic 并获取其错误信息
恢复后程序会从 recover 处继续执行

recover 只能捕获同一goroutine中的panic
*/

// 示例1: 基础panic和recover
func basicPanicRecover() {
	fmt.Println("=== 基础panic和recover示例 ===")

	// 使用defer和recover捕获panic
	defer func() {
		if err := recover(); err != nil {
			fmt.Printf("捕获到panic: %v\n", err)
			// 这里可以进行恢复操作，比如记录日志、释放资源等
		}
	}()

	fmt.Println("即将触发panic...")
	panic("这是一个模拟的panic错误") // 触发panic
	fmt.Println("这行不会被执行")  // 不会执行到这里
}

// 示例2: 在函数调用链中传递panic
func functionThatPanics() {
	fmt.Println("functionThatPanics: 即将触发panic...")
	panic("来自functionThatPanics的panic")
}

func callerFunction() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Printf("callerFunction捕获到panic: %v\n", err)
		}
	}()

	functionThatPanics() // 调用会panic的函数
	fmt.Println("这行不会被执行")
}

// 示例3: 实际应用场景 - 安全除法
func safeDivide(a, b int) (result int) {
	// 使用defer+recover处理可能的panic
	defer func() {
		if err := recover(); err != nil {
			fmt.Printf("安全除法捕获到panic: %v\n", err)
			result = 0 // 发生panic时返回默认值
		}
	}()

	if b == 0 {
		panic("除数不能为0") // 主动触发panic
	}
	return a / b
}

func main() {
	// 运行基础示例
	basicPanicRecover()

	fmt.Println("\n程序继续执行...") // 证明程序没有崩溃

	// 运行函数调用链示例
	callerFunction()

	fmt.Println("\n程序继续执行...") // 证明程序没有崩溃

	// 运行实际应用示例
	fmt.Println("安全除法测试:")
	fmt.Printf("10/2 = %d\n", safeDivide(10, 2)) // 正常情况
	fmt.Printf("10/0 = %d\n", safeDivide(10, 0)) // 除零panic情况
	fmt.Printf("8/4 = %d\n", safeDivide(8, 4))   // 正常情况

	fmt.Println("\n程序正常退出")
}
